package net.qiqbframework.common;

import java.util.Objects;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 常见的一些断言验证
 */
public abstract class Assert {

    private Assert() {
        // utility class
    }

    /**
     * 断言 的 state 值为 true。否则，将引发 IllegalStateException。
     */
    public static void state(boolean state, Supplier<String> messageSupplier) {
        if (!state) {
            throw new IllegalStateException(messageSupplier.get());
        }
    }

    /**
     * 断言给定 expression 为真。否则，将引发 IllegalArgumentException
     */
    public static void isTrue(boolean expression, Supplier<String> messageSupplier) {
        if (!expression) {
            throw new IllegalArgumentException(messageSupplier.get());
        }
    }

    /**
     * 断言给定 expression 是假的。否则，将引发 IllegalArgumentException
     */
    public static void isFalse(boolean expression, Supplier<String> messageSupplier) {
        if (expression) {
            throw new IllegalArgumentException(messageSupplier.get());
        }
    }

    /**
     * 断言给定 value 的不是 null。否则，将引发 IllegalArgumentException
     */
    public static void notNull(Object value, Supplier<String> messageSupplier) {
        isTrue(value != null, messageSupplier);
    }

    /**
     * 断言给定 value 的不是 null。否则，将引发 IllegalArgumentException
     */
    public static <T> T nonNull(T value, Supplier<String> messageSupplier) {
        isTrue(value != null, messageSupplier);
        return value;
    }

    /**
     * 断言给定 value 的结果 true 将通过 assertion Predicate.否则，则 exceptionSupplier 提供要引发的异常
     */
    @SuppressWarnings("RedundantThrows") // Throws signature required for correct compilation
    public static <T, X extends Throwable> void assertThat(T value,
                                                           Predicate<T> assertion,
                                                           Supplier<? extends X> exceptionSupplier) throws X {
        if (!assertion.test(value)) {
            throw exceptionSupplier.get();
        }
    }

    /**
     * 断言给定 value 为非 null。否则，则 exceptionSupplier 提供要引发的异常
     */
    public static <T, X extends Throwable> void assertNonNull(T value,
                                                              Supplier<? extends X> exceptionSupplier) throws X {
        assertThat(value, Objects::nonNull, exceptionSupplier);
    }
}
